package com.ciaojian.client.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ciaojian.client.service.*;
import com.ciaojian.core.base.annotation.ApiIdempotent;
import com.ciaojian.core.enums.business.CouponCodeTakeRecordTypeEnum;
import com.ciaojian.core.exception.EntityNotFoundException;
import com.ciaojian.core.model.Coupon;
import com.ciaojian.core.model.CouponCode;
import com.ciaojian.core.model.CouponGrantRecord;
import com.ciaojian.core.model.User;
import com.ciaojian.core.util.LogUtil;
import com.ciaojian.core.util.Result;
import com.ciaojian.miniapp.api.WxMiniAppApi;
import com.ciaojian.miniapp.model.request.submessage.BaseTemplate;
import com.ciaojian.miniapp.model.request.submessage.TakeCouponMessage;
import com.ciaojian.miniapp.model.request.submessage.TemplateIdEnum;
import com.ciaojian.miniapp.model.response.SubMessageSendResponse;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Optional;

/**
 * @author Atlakyn
 */
@Api(tags = "优惠券码接口")
@Validated
@RestController
@AllArgsConstructor
@RequestMapping("/coupon-codes")
public class CouponCodeController {
    private final CouponCodeServiceImpl couponCodeService;
    private final CouponServiceImpl couponService;
    private final UserServiceImpl userService;
    private final CouponGrantRecordServiceImpl couponGrantRecordService;
    private final OrderServiceImpl orderService;

    @ApiOperation("优惠券使用记录")
    @GetMapping("/history")
    public Result couponHistory(Integer userId,
                                @RequestParam(defaultValue = "0") Integer pageNo,
                                @RequestParam(defaultValue = "6") Integer pageSize) {
        return Result.ok(couponCodeService.couponHistory(new Page<>(pageNo, pageSize), userId));
    }

    @ApiOperation("领券")
    @PutMapping
    public Result put(@ApiParam("用户id") Integer userId,
                      @ApiParam("券类型id") Integer couponId,
                      @ApiParam("活动id") Integer activityId) {
        Assert.notNull(couponId, "券类型不能为空");
        Assert.notNull(activityId, "请选择活动");

        couponCodeService.advTakeCode(userId, couponId, activityId, CouponCodeTakeRecordTypeEnum.POP_ACTIVITY);
        return Result.ok();
    }

    @ApiOperation("券码领取")
    @PutMapping("/receive")
    public Result grant(@NotNull(message = "此券码不存在") @ApiParam(name = "recordId", value = "转赠记录ID") Integer recordId,
                        @NotNull(message = "被转赠方不存在") @ApiParam(name = "targetId", value = "被赠送人ID") Integer targetId) {
        CouponGrantRecord record = Optional.of(couponGrantRecordService.getById(recordId))
                .orElseThrow(() -> new EntityNotFoundException(CouponGrantRecord.class, "id", recordId));
        CouponCode couponCode = Optional.of(couponCodeService.lambdaQuery().eq(CouponCode::getCode, record.getCode()).one())
                .orElseThrow(() -> new EntityNotFoundException(CouponCode.class, "code", record.getCode()));
        Assert.isTrue(grantCondition(targetId, couponCode), "此券为新用户券，您不符合要求不能领取");
        Assert.isTrue(couponCode.getUserId() != null && couponCode.getUserId().compareTo(record.getSource()) == 0, "券码已被领取或已失效");
        Assert.isTrue(record.getTarget() == null, "券码已被领取或已失效");
        Assert.isTrue(couponCode.getStatus() != 2, "券码已被领取或失效");

        return Result.save(couponCodeService.receiveCode(targetId, couponCode, record));
    }

    /**
     * 领取条件判断
     *
     * @param targetId   被赠送方
     * @param couponCode 卡券券码
     * @return 可领取就返 TRUE
     */
    private Boolean grantCondition(Integer targetId, CouponCode couponCode) {
        // 硬编码430是用于赠送的券
        if (couponCode.getCouponId().equals(430)) {
            // 判断领取人的标签是否符合标签
            Integer flag = userService.getCustomerTypeByOrderNum(orderService.countNumberOfCompleteByUserId(targetId));
            // 只有未消费用户可领取
            return flag == 0;
        }
        return true;
    }

    @ApiOperation("券码转赠")
    @PutMapping("/grant")
    public Result grant(@NotNull(message = "转赠方不存在") @ApiParam(name = "grantId", value = "赠送人ID") Integer grantId,
                        @NotBlank(message = "转赠的券码不存在") @ApiParam(name = "code", value = "券码") String code) {
        CouponCode couponCode = Optional.of(couponCodeService.lambdaQuery().eq(CouponCode::getCode, code).one())
                .orElseThrow(() -> new IllegalArgumentException("转赠的券码不存在"));
        User granter = userService.getById(grantId);
        Assert.isTrue(couponCode.getUserId().compareTo(grantId) == 0, "券码已被领取或失效");
        Assert.isTrue(couponCode.getStatus() != 2, "券码已被领取或失效");

        return Result.save(couponCodeService.grantCode(granter, couponCode));
    }


    @ApiOperation("根据couponId查询券码名称")
    @GetMapping("/{couponId}")
    public Result get(@PathVariable Integer couponId) {
        Coupon one = couponService.lambdaQuery().select(Coupon::getTitle).eq(Coupon::getId, couponId).one();
        return Result.ok(one);
    }


    @ApiOperation("剪发支付完自动方法券发放券码(弹框)  (叠加券15 10 5)")
    @GetMapping("/checkHairOrder/{userId}")
    public Result checkConsum(@PathVariable int userId) {
        return couponCodeService.checkHairOrder(userId);
    }

    /**
     * 弃用 融合到 /checkHairOrder/{userId}
     * @param userId
     * @param couponId
     * @param openId
     * @return
     */
    @ApiOperation("剪发支付完自动方法券发放券码  (叠加券  15 10 5)")
    @Transactional(rollbackFor = Exception.class)
    @PutMapping("/checkConsum/{userId}/{couponId}")
    public Result checkConsum(@PathVariable int userId,
                              @PathVariable int couponId,
                              @RequestParam String openId) {
        return couponCodeService.checkConsum(userId,couponId,openId);
    }


}
